package ru.spb.osll.myfit.client.view;

import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.*;
import ru.spb.osll.myfit.client.PageMode;
import ru.spb.osll.myfit.client.dialog.ErrorDialog;
import ru.spb.osll.myfit.client.event.PageButtonEvent;
import ru.spb.osll.myfit.client.manager.PageExecutingManager;
import ru.spb.osll.myfit.client.service.FitService;
import ru.spb.osll.myfit.client.service.FitServiceAsync;
import ru.spb.osll.myfit.client.widget.*;
import ru.spb.osll.myfit.common.Page;
import ru.spb.osll.myfit.common.PageElement;
import ru.spb.osll.myfit.common.PageExecutingResult;
import ru.spb.osll.myfit.common.PageExecutingResultComparatorFactory;
import ru.spb.osll.myfit.common.PageExecutingResultComparatorFactory.ComparatorType;

import java.util.Collections;
import java.util.List;
import java.util.Vector;

public class TestResultsView extends AbstractView {

  public enum ViewMode {
    TABLE, PAGE_RESULT;
  }

  private static final String DEFAULT_TITLE = "Tests Results";

  private PageButtonEventListener m_buttonEventListener = createButtonEventListener();
  private final Label m_titleLabel = new Label(DEFAULT_TITLE);
  private ResultTableWidget m_tableWidget = new ResultTableWidget();

  private ViewMode m_mode;
  private PageWidget m_pageWidget = new PageWidget(new GWTWidgetFactory());
  private FitServiceAsync m_fitService = GWT.create(FitService.class);
  private DialogBox m_errorDialog = new ErrorDialog();

  private PageExecutingManager m_pageExecutingManager = new PageExecutingManager();
  private String m_pageId;
  private String m_pagePath;
  private PageExecutingResult m_PageExecutingResult;

  private ProgressBar myProgressBar;
  private ProgressLabel myProgressLabel;

  public TestResultsView() {
    m_titleLabel.addStyleName("testResultTextStyle");
    m_titleLabel.setWidth("300px");
    m_mode = ViewMode.TABLE;
    m_tableWidget.addResultTableEventListener(createResultTableEventListener());
    createRootPanel();
  }

  private ResultTableEventListener createResultTableEventListener() {
    ResultTableEventListener listener = new ResultTableEventListener() {

      @Override
      public void actionPerformed(ResultTableEvent event) {
        switch (event.getType()) {
        case OPEN_PAGE_RESULT:
          m_tableWidget.removeFromParent();
          m_mode = ViewMode.PAGE_RESULT;
          
          m_PageExecutingResult = event.getResult();
          m_pageId = m_PageExecutingResult.getID();
          m_pagePath = m_PageExecutingResult.getName();

          m_pageExecutingManager = new PageExecutingManager();
          m_pageWidget.clear();
          m_pageWidget.setMode(PageMode.VIEW);
          m_pageWidget.setPagePath(m_pagePath);

          m_fitService.loadPageFromTestResultsDirectory(m_pagePath, m_pageId,
              new AsyncCallback<Page>() {

                @Override
                public void onFailure(Throwable caught) {
                  caught.printStackTrace();
                  m_errorDialog.center();
                }

                @Override
                public void onSuccess(Page page) {
                  loadTestsPage(page);
                }
              });
        }
      }
    };
    return listener;
  }

  private PageButtonEventListener createButtonEventListener() {
    PageButtonEventListener listener = new PageButtonEventListener() {

      @Override
      public void actionPerformed(PageButtonEvent event) {
        switch (event.getType()) {
        case BACK:
          if (m_mode.equals(ViewMode.TABLE)) {
            backToStartPage();
          } else {
            backToTableWidget();
          }
          break;
        }
      }
    };
    return listener;
  }

  private void loadTestsPage(Page page) {
    loadTestsResult(page);
    loadProgressBar();

    setProgressVisible(true);
    m_pageWidget.setOpen(true);

    m_rootPanel.add(m_pageWidget);
  }

  private void loadProgressBar() {
    myProgressBar.updateView(m_PageExecutingResult.getCounts());
    myProgressLabel.updateView(m_PageExecutingResult.getCounts());
    if (!m_PageExecutingResult.getState().equals(
        PageExecutingResult.PageExecutingState.FINISH)) {
      m_pageExecutingManager.addListener(m_pageId, myProgressBar);
      m_pageExecutingManager.addListener(m_pageId, myProgressLabel);
    }
  }

  private void loadTestsResult(Page page) {

    m_titleLabel.setText(m_PageExecutingResult.getName());

    Vector<PageElement> pageElements = page.getElements();
    for (PageElement e : pageElements) {
      m_pageWidget.addPageElementWidget(e);
    }

    m_pageExecutingManager.addListener(m_pageId, new PageExecutingListenerImpl(
        m_pageWidget));
    m_pageExecutingManager.addResultToListen(m_PageExecutingResult);
  }

  private void backToTableWidget() {
    m_mode = ViewMode.TABLE;
    m_pageWidget.clear();
    m_pageWidget.removeFromParent();
    setProgressVisible(false);
    m_titleLabel.setText(DEFAULT_TITLE);
    m_rootPanel.add(m_tableWidget);
  }

  private void backToStartPage() {
    Window.open(ViewConstants.START_PAGE, "", "");
  }

  private void setProgressVisible(boolean isVisible) {
    myProgressBar.setVisible(isVisible);
    myProgressLabel.setVisible(isVisible);
  }

  @Override
  protected Widget createContentPanel() {
    return m_tableWidget;
  }

  @Override
  protected void createEditPanel() {
    super.createEditPanel();
    m_editPanel.add(m_titleLabel);
    m_editPanel.add(createButtonPanel());

  }

  private Widget createButtonPanel() {
    Panel buttonPanel = new HorizontalPanel();
    buttonPanel.setWidth("100%");

    HorizontalPanel hPanel = new HorizontalPanel();
    hPanel.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_LEFT);
    hPanel.setSpacing(5);
    hPanel.add(new PageButton("Back to Test page", "backToTestButtonStyle",
        PageButtonEvent.PageButtonEventType.BACK, m_buttonEventListener));
    buttonPanel.add(hPanel);
    buttonPanel.add(createProgressPanel());
    return buttonPanel;
  }

  private Widget createProgressPanel() {
    HorizontalPanel panel = new HorizontalPanel();
    panel.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_RIGHT);
    panel.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE);
    panel.setSpacing(5);
    myProgressBar = new ProgressBar();
    myProgressLabel = new ProgressLabel();
    panel.setWidth("100%");
    panel.add(myProgressLabel);
    panel.add(myProgressBar);
    panel.setCellWidth(myProgressBar, "250px");
    return panel;
  }

  public void addResultToWidget(List<PageExecutingResult> list) {
    if (list != null) {
      Collections.sort(list, PageExecutingResultComparatorFactory.createComparator(ComparatorType.BY_NAME));
      for (PageExecutingResult result : list) {
        m_tableWidget.addResult(result);
      }
    }
  }

  public void updateResult(PageExecutingResult result) {
    m_tableWidget.updateResult(result);
  }
}
